From 2c0ba8d0753536c7cd9651b0326bcfabd2d20e18 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Wed, 14 Sep 2005 08:41:49 +0000 Subject: [PATCH] Fix xenstored watch crash. When a connection blocked waiting on a transaction, don't queue watch events. Sure, they'd be ignored and re-transmitted, but it hits an assert that we don't send data out blocked connections, and it's wasteful. Signed-off-by: Rusty Russell (authored) Signed-off-by: Christian Limpach --- .../xenstore/testsuite/16block-watch-crash.test | 13 +++++++++++++ tools/xenstore/xenstored_watch.c | 2 +- tools/xenstore/xs_test.c | 16 ++++++++++------ 3 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 tools/xenstore/testsuite/16block-watch-crash.test diff --git a/tools/xenstore/testsuite/16block-watch-crash.test b/tools/xenstore/testsuite/16block-watch-crash.test new file mode 100644 index 0000000000..564f6d31ed --- /dev/null +++ b/tools/xenstore/testsuite/16block-watch-crash.test @@ -0,0 +1,13 @@ +# Test case where blocked connection gets sent watch. + +mkdir /test +watch /test token +1 start /test +# This will block on above +noackwrite /test/entry create contents +1 write /test/entry2 create contents +1 commit +readack +expect /test/entry2:token +waitwatch +ackwatch token diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c index e40318ee2f..a543f8a495 100644 --- a/tools/xenstore/xenstored_watch.c +++ b/tools/xenstore/xenstored_watch.c @@ -144,7 +144,7 @@ void fire_watches(struct connection *conn, const char *node, bool recurse) else continue; /* If connection not doing anything, queue this. */ - if (!i->out) + if (i->state == OK) queue_next_event(i); } } diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c index 58445b9f25..6f4d0d5bc4 100644 --- a/tools/xenstore/xs_test.c +++ b/tools/xenstore/xs_test.c @@ -398,12 +398,16 @@ static void do_noackwrite(unsigned int handle, static void do_readack(unsigned int handle) { enum xsd_sockmsg_type type; - char *ret; - - ret = read_reply(handles[handle]->fd, &type, NULL); - if (!ret) - failed(handle); - free(ret); + char *ret = NULL; + + /* Watches can have fired before reply comes: daemon detects + * and re-transmits, so we can ignore this. */ + do { + free(ret); + ret = read_reply(handles[handle]->fd, &type, NULL); + if (!ret) + failed(handle); + } while (type == XS_WATCH_EVENT); } static void do_setid(unsigned int handle, char *id) -- 2.30.2